/**
 * $Revision: 1.1 $
 * $Date: 2010/06/28 07:02:26 $
 *
 * Copyright (C) 2006 Jive Software. All rights reserved.
 *
 * This software is published under the terms of the GNU Lesser Public License (LGPL),
 * a copy of which is included in this distribution.
 */

package org.jivesoftware.spark.ui.conferences;

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.DefaultListModel;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.ListCellRenderer;
import javax.swing.SwingUtilities;


import org.jdesktop.swingx.JXList;
import org.jivesoftware.resource.Res;
import org.jivesoftware.resource.SparkRes;
import org.jivesoftware.smack.PacketListener;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smack.packet.Presence;
import org.jivesoftware.smack.packet.XMPPError;
import org.jivesoftware.smack.util.StringUtils;
import org.jivesoftware.smackx.ServiceDiscoveryManager;
import org.jivesoftware.smackx.muc.Affiliate;
import org.jivesoftware.smackx.muc.InvitationRejectionListener;
import org.jivesoftware.smackx.muc.MultiUserChat;
import org.jivesoftware.smackx.muc.Occupant;
import org.jivesoftware.smackx.muc.UserStatusListener;
import org.jivesoftware.smackx.packet.DiscoverInfo;
import org.jivesoftware.smackx.packet.VCard;
import org.jivesoftware.spark.ChatManager;
import org.jivesoftware.spark.PresenceManager;
import org.jivesoftware.spark.SparkManager;
import org.jivesoftware.spark.UserManager;
import org.jivesoftware.spark.component.ImageTitlePanel;
import org.jivesoftware.spark.ui.ChatRoom;
import org.jivesoftware.spark.ui.ChatRoomListener;
import org.jivesoftware.spark.ui.ChatRoomNotFoundException;
import org.jivesoftware.spark.ui.rooms.ChatRoomImpl;
import org.jivesoftware.spark.ui.rooms.GroupChatRoom;
import org.jivesoftware.spark.util.ModelUtil;
import org.jivesoftware.spark.util.log.Log;

import cn.newgrand.common.NetcallUtil;
import cn.newgrand.common.StringUtil;
import cn.newgrand.netcall.muc.MUCUtil;

/**
 * The <code>RoomInfo</code> class is used to display all room information, such
 * as agents and room information.
 */
public final class GroupChatParticipantList extends JPanel implements
		ChatRoomListener {
	private GroupChatRoom groupChatRoom;
	private final ImageTitlePanel agentInfoPanel;
	private ChatManager chatManager;
	private MultiUserChat chat;

	private final Map<String, String> userMap = new HashMap<String, String>();

	private UserManager userManager = SparkManager.getUserManager();

	private DefaultListModel model = new DefaultListModel();

	private JXList participantsList;

	private PacketListener listener = null;

	private Map<String, String> invitees = new HashMap<String, String>();

	private boolean allowNicknameChange = true;

	private DiscoverInfo roomInformation;

	private List<JLabel> users = new ArrayList<JLabel>();
	
	//modified by sidney
	private List<JLabel> offlineMembers = new ArrayList<JLabel>();
	
	private Map<String,Affiliate> membersMap = new HashMap<String, Affiliate>();
	private Map<String, String> userNickMap = new HashMap<String, String>();
	private Map<String, String> nickJIDMap = new HashMap<String, String>();
	private boolean isInited = false;
	private Map<String, String> statMap = new HashMap<String, String>();
	
	private Set<String> owners = new HashSet<String>();
	private Set<String> admins = new HashSet<String>();
	private Set<String> members = new HashSet<String>();
	

	/**
	 * Creates a new RoomInfo instance using the specified ChatRoom. The
	 * RoomInfo component is responsible for monitoring all activity in the
	 * ChatRoom.
	 */
	public GroupChatParticipantList() {
		setLayout(new GridBagLayout());
		chatManager = SparkManager.getChatManager();

		agentInfoPanel = new ImageTitlePanel(Res
				.getString("message.participants.in.room"));
		participantsList = new JXList(model);
		participantsList.setCellRenderer(new ParticipantRenderer());

		// Set the room to track
		this.setOpaque(false);
		this.setBackground(Color.white);

		// Respond to Double-Click in Agent List to start a chat
		participantsList.addMouseListener(new MouseAdapter() {
			public void mouseClicked(MouseEvent evt) {
				if (evt.getClickCount() == 2) {
					String selectedUser = getSelectedUser();
					//startChat(groupChatRoom, userMap.get(selectedUser));
					startChat(groupChatRoom, nickJIDMap.get(selectedUser));
				}
			}

			public void mouseReleased(final MouseEvent evt) {
				if (evt.isPopupTrigger()) {
					checkPopup(evt);
				}
			}

			public void mousePressed(final MouseEvent evt) {
				if (evt.isPopupTrigger()) {
					checkPopup(evt);
				}
			}
		});

		JScrollPane scroller = new JScrollPane(participantsList);

		// Speed up scrolling. It was way too slow.
		scroller.getVerticalScrollBar().setBlockIncrement(50);
		scroller.getVerticalScrollBar().setUnitIncrement(20);
		scroller.setBackground(Color.white);
		scroller.getViewport().setBackground(Color.white);

		add(scroller, new GridBagConstraints(0, 0, 1, 1, 1.0, 1.0,
				GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(
						0, 0, 0, 0), 0, 0));
		JButton btn = new JButton("come on!!!");
		btn.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent arg0) {
//				 String nickName = chat.getReservedNickname(SparkManager.getSessionManager().getJID());
//				 System.out.println(nickName);
//				Presence p = SparkManager.getConnection().getRoster().getPresence("wq@sww-pc");
//				System.out.println(p.getType());
//				System.out.println(chat.getReservedNickname("xc@sww-pc"));
				try {
					//MultiUserChat.getHostedRooms(SparkManager.getConnection(),MUCUtil.getChinaGroupServiceName());
					//MultiUserChat.getRoomInfo(SparkManager.getConnection(), "01q@chinagroup.sww-pc");
					chat.getAdmins();
				} catch (XMPPException e) {
					e.printStackTrace();
				}
//				try {
//					for(Affiliate aff :chat.getMembers()){
//						System.out.println("aff.getJid()="+aff.getJid()+"  ||  "+"aff.getNick()="+aff.getNick()); 
//					}
//				} catch (XMPPException e) {
//					e.printStackTrace();
//				}
			}
		});
//		add(btn, new GridBagConstraints(0, 1, 1, 1, 1.0, 1.0,
//				GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(
//						0, 0, 0, 0), 0, 0));
	}

	public void setChatRoom(final ChatRoom chatRoom) {
		this.groupChatRoom = (GroupChatRoom) chatRoom;

		chatManager.addChatRoomListener(this);

		chat = groupChatRoom.getMultiUserChat();

		chat.addInvitationRejectionListener(new InvitationRejectionListener() {
			public void invitationDeclined(String jid, String message) {
				String nickname = userManager.getUserNicknameFromJID(jid);

				userHasLeft(chatRoom, nickname);

				chatRoom.getTranscriptWindow().insertNotificationMessage(Res.getString("message.conference.invite.reject.info",nickname)
						,ChatManager.NOTIFICATION_COLOR);
			}
		});

		listener = new PacketListener() {
			//添加packet监听器以后，xmppConnection会执行处理消息包，
			//这里的处理跟groupchat获取群成员列表的线程处理有个先后关系的问题
			public void processPacket(final Packet packet) {
				SwingUtilities.invokeLater(new Runnable() {
					public  void run() {
						Presence p = (Presence) packet;
						if (p.getError() != null) {
							if (p.getError().getCondition().equals(
									XMPPError.Condition.conflict.toString())) {
								return;
							}
						}
						final String userid = p.getFrom();
						
						String displayName = StringUtils.parseResource(userid);
						userMap.put(displayName, userid);
						//在接到presence更新在线成员之前，先加载所有的成员、管理者以及拥有者
						//modified by sidney 
						if(groupChatRoom.isChinaGroupRoom()){
							initMemebersInfo();
						}
						if (p.getType() == Presence.Type.available) {
							statMap.put(displayName, userid);
							addParticipant(userid, p);
							agentInfoPanel.setVisible(true);
						} else {
							statMap.remove(displayName);
							changeOnlineStatus(displayName);
						}
					}
				});

			}
		};

		chat.addParticipantListener(listener);

		ServiceDiscoveryManager disco = ServiceDiscoveryManager
				.getInstanceFor(SparkManager.getConnection());
		try {
			roomInformation = disco.discoverInfo(chat.getRoom());
		} catch (XMPPException e) {
			Log.debug("Unable to retrieve room informatino for "
					+ chat.getRoom());
		}
	}

	public void chatRoomOpened(ChatRoom room) {
		if (room != groupChatRoom) {
			return;
		}

		chat.addUserStatusListener(new UserStatusListener() {
			public void kicked(String actor, String reason) {

			}

			public void voiceGranted() {

			}

			public void voiceRevoked() {

			}

			public void banned(String actor, String reason) {

			}

			public void membershipGranted() {

			}

			public void membershipRevoked() {

			}

			public void moderatorGranted() {

			}

			public void moderatorRevoked() {

			}

			public void ownershipGranted() {
			}

			public void ownershipRevoked() {

			}

			public void adminGranted() {

			}

			public void adminRevoked() {

			}
		});
	}

	public void chatRoomLeft(ChatRoom room) {
		if (this.groupChatRoom == room) {
			chatManager.removeChatRoomListener(this);
			agentInfoPanel.setVisible(false);
		}
	}

	public void chatRoomClosed(ChatRoom room) {
		if (this.groupChatRoom == room) {
			chatManager.removeChatRoomListener(this);
			chat.removeParticipantListener(listener);
		}
	}

	public void chatRoomActivated(ChatRoom room) {
	}

	public void userHasJoined(ChatRoom room, String userid) {
	}

	public void addInvitee(String jid, String message) {
		// So the problem with this is that I have no idea what the users actual
		// jid is in most cases.
		final UserManager userManager = SparkManager.getUserManager();

		String displayName = userManager.getUserNicknameFromJID(jid);

		groupChatRoom.getTranscriptWindow().insertNotificationMessage(
				displayName + " has been invited to join this room.",
				ChatManager.NOTIFICATION_COLOR);

		if (roomInformation != null
				&& !roomInformation.containsFeature("muc_nonanonymous")) {
			return;
		}

		final ImageIcon inviteIcon = SparkRes
				.getImageIcon(SparkRes.USER1_BACK_16x16);

		addUser(inviteIcon, displayName);

		invitees.put(displayName, message);
	}

	private ImageIcon getImageIcon(String participantJID) {
		String displayName = StringUtils.parseResource(participantJID);
		ImageIcon icon = SparkRes.getImageIcon(SparkRes.IM_MEMBER_AVAILABLE);
		icon.setDescription(displayName);
		return icon;
	}

	private void addParticipant(String participantJID, Presence presence) {
		// Remove reference to invitees
		for (String displayName : invitees.keySet()) {
			String jid = SparkManager.getUserManager().getJIDFromDisplayName(
					displayName);

			Occupant occ = chat.getOccupant(participantJID);
			if (occ != null) {
				String actualJID = occ.getJid();
				if (actualJID.equals(jid)) {
					removeUser(displayName);
				}
			}
		}

		String nickname = StringUtils.parseResource(participantJID);
		
		if (!exists(nickname)) {
			Icon icon;
			removeRepeatName(nickname);
			//icon = PresenceManager.getIconFromPresence(presence);
			icon = getOnlineImageIcon(nickJIDMap.get(nickname));
			if (icon == null) {
				icon = SparkRes.getImageIcon(SparkRes.IM_MEMBER_AVAILABLE);
			}
			addUser(icon, nickname);
			int index = getIndex(nickname);
			if (index != -1&&index != (statMap.size()-1)) {
				JLabel onlineLable = (JLabel)model.getElementAt(index);
				JLabel label = (JLabel)model.getElementAt(statMap.size()-1);
				model.setElementAt(label, index);
				model.setElementAt(onlineLable, statMap.size()-1);
			}
		} else {
			//Icon icon = PresenceManager.getIconFromPresence(presence);
			Icon icon = getOnlineImageIcon(nickJIDMap.get(nickname));
			if (icon == null) {
				icon = SparkRes.getImageIcon(SparkRes.IM_MEMBER_AVAILABLE);
			}

			int index = getIndex(nickname);
			if (index != -1) {
				JLabel onlineLable = (JLabel)model.getElementAt(index);
				onlineLable.setIcon(icon);
				if(index != (statMap.size()-1)){
					JLabel label = (JLabel)model.getElementAt(statMap.size()-1);
					model.setElementAt(label, index);
					model.setElementAt(onlineLable, statMap.size()-1);
				}
//				final JLabel userLabel = new JLabel(nickname, icon,
//						JLabel.HORIZONTAL);
//				model.setElementAt(userLabel, index);
			}
		}
	}
	
	public void removeRepeatName(String nickname){
		try {
			for(Affiliate aff:chat.getMembers()){
				if(nickname.equals(aff.getNick())){
					String username = StringUtils.parseName(aff.getJid());
					String oldNickName = userNickMap.get(username);
					userNickMap.put(username, nickname);
					nickJIDMap.put(aff.getNick(), aff.getJid());
					nickJIDMap.remove(oldNickName);
					//userMap.put(nickname, aff.getJid());
					//userMap.remove(oldNickName);
					removeUser(oldNickName);
				}
			}
		} catch (XMPPException e) {
			e.printStackTrace();
		}
		try {
			for(Affiliate aff:chat.getOwners()){
				if(nickname.equals(aff.getNick())){
					String username = StringUtils.parseName(aff.getJid());
					String oldNickName = userNickMap.get(username);
					userNickMap.put(username, nickname);
					nickJIDMap.put(aff.getNick(), aff.getJid());
					nickJIDMap.remove(oldNickName);
					//userMap.put(nickname, aff.getJid());
					//userMap.remove(oldNickName);
					removeUser(oldNickName);
				}
			}
		} catch (XMPPException e) {
			e.printStackTrace();
		}
		try {
			for(Affiliate aff:chat.getAdmins()){
				if(nickname.equals(aff.getNick())){
					String username = StringUtils.parseName(aff.getJid());
					String oldNickName = userNickMap.get(username);
					userNickMap.put(username, nickname);
					nickJIDMap.put(aff.getNick(), aff.getJid());
					nickJIDMap.remove(oldNickName);
					//userMap.put(nickname, aff.getJid());
					//userMap.remove(oldNickName);
					removeUser(oldNickName);
				}
			}
		} catch (XMPPException e) {
			e.printStackTrace();
		}
	}

	public void userHasLeft(ChatRoom room, String userid) {
		if (room != groupChatRoom) {
			return;
		}

		int index = getIndex(userid);

		if (index != -1) {
			//removeUser(userid);
			//userMap.remove(userid);
			changeOnlineStatus(userid);
		}
	}

	private boolean exists(String nickname) {
		for (int i = 0; i < model.getSize(); i++) {
			final JLabel userLabel = (JLabel) model.getElementAt(i);
			if (userLabel.getText().equals(nickname)) {
				return true;
			}
		}
		return false;
	}

	private String getSelectedUser() {
		JLabel label = (JLabel) participantsList.getSelectedValue();
		if (label != null) {
			return label.getText();
		}

		return null;
	}

	private void startChat(ChatRoom groupChat, String groupJID) {
		//如果群聊中快速聊天弹出的对话框和单聊弹出相同的对话框
		//那么此时的groupJID应该是groupJID中昵称对应的userJID
		//那么昵称应该对应一个userJID
		//modified by sww(注释下面代码,直接激活房间)
		if(groupJID.equals(SparkManager.getSessionManager().getBareAddress())){
			return;
		}
		SparkManager.getChatManager().activateChat(groupJID, StringUtils.parseName(groupJID));
		/*
		String userNickname = StringUtils.parseResource(groupJID);
		//离线的用户获取不到昵称.根据实际选择的获取昵称..
		if("".equals(userNickname)){
			JLabel selectedUserLabel = (JLabel)participantsList.getSelectedValue();
			userNickname = selectedUserLabel.getText();
		}
		String roomTitle = userNickname + " - " + StringUtils.parseName(groupChat.getRoomname());

		String nicknameOfUser = StringUtils.parseResource(groupJID);
		String nickname = groupChat.getNickname();

		if (nicknameOfUser.equals(nickname)) {
			return;
		}
		ChatRoom chatRoom;
		try {
			chatRoom = chatManager.getChatContainer().getChatRoom(groupJID);
		} catch (ChatRoomNotFoundException e) {
			Log.debug("Could not find chat room - " + groupJID);

			// Create new room
			chatRoom = new ChatRoomImpl(groupJID, nicknameOfUser, roomTitle);
			chatManager.getChatContainer().addChatRoom(chatRoom);
		}

		chatManager.getChatContainer().activateChatRoom(chatRoom);
		*/
	}

	public void tabSelected() {
		// To change body of implemented methods use File | Settings | File
		// Templates.
	}

	public String getTabTitle() {
		return Res.getString("title.room.information");
	}

	public Icon getTabIcon() {
		return SparkRes.getImageIcon(SparkRes.SMALL_BUSINESS_MAN_VIEW);
	}

	public String getTabToolTip() {
		return Res.getString("title.room.information");
	}

	public JComponent getGUI() {
		return this;
	}

	private void kickUser(String nickname) {
		try {
			chat.kickParticipant(nickname, Res
					.getString("message.you.have.been.kicked"));
		} catch (XMPPException e) {
			groupChatRoom.insertText(Res.getString("message.kicked.error",
					nickname));
		}
	}

	private void banUser(String displayName) {
		try {
			Occupant occupant = chat.getOccupant(userMap.get(displayName));
			if (occupant != null) {
				String bareJID = StringUtils
						.parseBareAddress(occupant.getJid());
				chat.banUser(bareJID, Res
						.getString("message.you.have.been.banned"));
			}
		} catch (XMPPException e) {
			Log.error(e);
		}
	}

	private void unbanUser(String jid) {
		try {
			chat.grantMembership(jid);
		} catch (XMPPException e) {
			Log.error(e);
		}
	}

	private void grantVoice(String nickname) {
		try {
			chat.grantVoice(nickname);
		} catch (XMPPException e) {
			Log.error(e);
		}
	}

	private void revokeVoice(String nickname) {
		try {
			chat.revokeVoice(nickname);
		} catch (XMPPException e) {
			Log.error(e);
		}
	}

	private void grantModerator(String nickname) {
		try {
			chat.grantModerator(nickname);
		} catch (XMPPException e) {
			Log.error(e);
		}
	}

	private void revokeModerator(String nickname) {
		try {
			chat.revokeModerator(nickname);
		} catch (XMPPException e) {
			Log.error(e);
		}
	}
	
	private void removeMember(String jid){
		try {
			chat.removeMember(jid);
		} catch (XMPPException e) {
			Log.error(e);
		}
	}

	/**
	 * Let's make sure that the panel doesn't strech past the scrollpane view
	 * pane.
	 * 
	 * @return the preferred dimension
	 */
	public Dimension getPreferredSize() {
		final Dimension size = super.getPreferredSize();
		size.width = 150;
		return size;
	}

	private void checkPopup(MouseEvent evt) {
		Point p = evt.getPoint();
		final int index = participantsList.locationToIndex(p);

		final JPopupMenu popup = new JPopupMenu();
		final boolean admin = SparkManager.getUserManager().isOwnerOrAdmin(
				groupChatRoom, chat.getNickname());
		final boolean isAdminOrOwner = userIsAdminOrOwner(StringUtils.parseBareAddress(SparkManager.getSessionManager().getJID()));
		final boolean owner = SparkManager.getUserManager().isOwner(groupChatRoom, chat.getNickname());

		if (index != -1) {
			participantsList.setSelectedIndex(index);
			final JLabel userLabel = (JLabel) model.getElementAt(index);
			final String selectedUser = userLabel.getText();
			final String groupJID = userMap.get(selectedUser);
			String groupJIDNickname = StringUtils.parseResource(groupJID);
			final String nickname = groupChatRoom.getNickname();
			final Occupant occupant = userManager.getOccupant(groupChatRoom,
					selectedUser);
			
			final boolean moderator = SparkManager.getUserManager()
					.isModerator(groupChatRoom, chat.getNickname());

			final boolean userIsAdmin = userManager.isOwnerOrAdmin(occupant);
			final boolean userIsModerator = userManager.isModerator(occupant);
			boolean isMe = nickname.equals(groupJIDNickname);
			final boolean selUserIsAdmin = selectedUserIsAdmin(nickJIDMap.get(selectedUser));
			final boolean selUserIsAdminOrOwner = userIsAdminOrOwner(nickJIDMap.get(selectedUser));
			// Handle invites
			if (groupJIDNickname == null) {
				Action inviteAgainAction = new AbstractAction() {
					public void actionPerformed(ActionEvent actionEvent) {
						String message = invitees.get(selectedUser);
						String jid = userManager
								.getJIDFromDisplayName(selectedUser);
						chat.invite(jid, message);
					}
				};

				inviteAgainAction.putValue(Action.NAME, "Invite Again");
				popup.add(inviteAgainAction);

				Action removeInvite = new AbstractAction() {
					public void actionPerformed(ActionEvent actionEvent) {
						int index = getIndex(selectedUser);

						if (index != -1) {
							model.removeElementAt(index);
						}
					}
				};

				removeInvite.putValue(Action.NAME, "Remove");
				popup.add(removeInvite);

				popup.show(participantsList, evt.getX(), evt.getY());
				return;
			}

			if (isMe) {
				Action changeNicknameAction = new AbstractAction() {
					public void actionPerformed(ActionEvent actionEvent) {
						String newNickname = JOptionPane.showInputDialog(
								groupChatRoom, Res
										.getString("label.new.nickname")
										+ ":", Res
										.getString("title.change.nickname"),
								JOptionPane.QUESTION_MESSAGE);
						if (ModelUtil.hasLength(newNickname)) {
							while (true) {
								newNickname = newNickname.trim();
								String nick = chat.getNickname();
								if (newNickname.equals(nick)) {
									// return;
								}
								try {
									chat.changeNickname(newNickname);
									break;
								} catch (XMPPException e1) {
									newNickname = JOptionPane
											.showInputDialog(
													groupChatRoom,
													Res
															.getString("message.nickname.in.use")
															+ ":",
													Res
															.getString("title.change.nickname"),
													JOptionPane.QUESTION_MESSAGE);
									if (!ModelUtil.hasLength(newNickname)) {
										break;
									}
								}
							}
						}
					}
				};

				changeNicknameAction.putValue(Action.NAME, Res
						.getString("menuitem.change.nickname"));
				changeNicknameAction.putValue(Action.SMALL_ICON, SparkRes
						.getImageIcon(SparkRes.DESKTOP_IMAGE));

				if (allowNicknameChange) {
					popup.add(changeNicknameAction);
				}
			}

			Action chatAction = new AbstractAction() {
				public void actionPerformed(ActionEvent actionEvent) {
					String selectedUser = getSelectedUser();
					//startChat(groupChatRoom, userMap.get(selectedUser));
					startChat(groupChatRoom, nickJIDMap.get(selectedUser));
				}
			};

			chatAction.putValue(Action.NAME, Res
					.getString("menuitem.start.a.chat"));
			chatAction.putValue(Action.SMALL_ICON, SparkRes
					.getImageIcon(SparkRes.SMALL_MESSAGE_IMAGE));
			if (!isMe) {
				popup.add(chatAction);
			}

			Action blockAction = new AbstractAction() {
				public void actionPerformed(ActionEvent e) {
					String user = getSelectedUser();
					ImageIcon icon;
					if (groupChatRoom.isBlocked(groupJID)) {
						groupChatRoom.removeBlockedUser(groupJID);
						icon = getImageIcon(groupJID);
					} else {
						groupChatRoom.addBlockedUser(groupJID);
						icon = SparkRes.getImageIcon(SparkRes.BRICKWALL_IMAGE);
					}

					JLabel label = new JLabel(user, icon, JLabel.HORIZONTAL);
					model.setElementAt(label, index);
				}
			};

			blockAction.putValue(Action.NAME, Res
					.getString("menuitem.block.user"));
			blockAction.putValue(Action.SMALL_ICON, SparkRes
					.getImageIcon(SparkRes.BRICKWALL_IMAGE));
			if (!isMe) {
				if (groupChatRoom.isBlocked(groupJID)) {
					blockAction.putValue(Action.NAME, Res
							.getString("menuitem.unblock.user"));
				}
				popup.add(blockAction);
			}

			Action kickAction = new AbstractAction() {
				public void actionPerformed(ActionEvent actionEvent) {
					kickUser(selectedUser);
					if(groupChatRoom.isChinaGroupRoom()){
						//modified by sidney
						//删除会员资格(不在线的从userMap中取jid)
						if(occupant!=null){
							removeMember(NetcallUtil.getBareJID(occupant.getJid()));
						}else{
							String jid = userMap.get(selectedUser);
							removeMember(jid);
						}
						//在群聊用户的显示列表去掉用户
						removeUser(selectedUser);
					}
				}
			};

			kickAction.putValue(Action.NAME, Res
					.getString("menuitem.kick.user"));
			kickAction.putValue(Action.SMALL_ICON, SparkRes
					.getImageIcon(SparkRes.SMALL_DELETE));
			if (moderator && !userIsAdmin && !isMe &&!selUserIsAdminOrOwner) {
				popup.add(kickAction);
			}

			// Handle Voice Operations
			Action voiceAction = new AbstractAction() {
				public void actionPerformed(ActionEvent actionEvent) {
					if (userManager.hasVoice(groupChatRoom, selectedUser)) {
						revokeVoice(selectedUser);
					} else {
						grantVoice(selectedUser);
					}

				}
			};
			Action banAction = new AbstractAction() {
				public void actionPerformed(ActionEvent actionEvent) {
					banUser(selectedUser);
				}
			};
			Action moderatorAction = new AbstractAction() {
				public void actionPerformed(ActionEvent actionEvent) {
					if (!userIsModerator) {
						grantModerator(selectedUser);
					} else {
						revokeModerator(selectedUser);
					}
				}
			};
			// Handle Unbanning of users.
			Action unbanAction = new AbstractAction() {
				public void actionPerformed(ActionEvent actionEvent) {
					String jid = ((JMenuItem) actionEvent.getSource())
							.getText();
					unbanUser(jid);
				}
			};
			//如果是chinaGroup则添加右键菜单
			//modified by sidney
			if(!groupChatRoom.isChinaGroupRoom()){

			voiceAction.putValue(Action.NAME, Res.getString("menuitem.voice"));
			voiceAction.putValue(Action.SMALL_ICON, SparkRes
					.getImageIcon(SparkRes.MEGAPHONE_16x16));
			if (moderator && !userIsModerator && !isMe) {
				if (userManager.hasVoice(groupChatRoom, selectedUser)) {
					voiceAction.putValue(Action.NAME, Res
							.getString("menuitem.revoke.voice"));
				} else {
					voiceAction.putValue(Action.NAME, Res
							.getString("menuitem.grant.voice"));
				}
				popup.add(voiceAction);
			}

			
			banAction.putValue(Action.NAME, Res.getString("menuitem.ban.user"));
			banAction.putValue(Action.SMALL_ICON, SparkRes
					.getImageIcon(SparkRes.RED_FLAG_16x16));
			if (admin && !userIsModerator && !isMe) {
				popup.add(banAction);
			}

			moderatorAction.putValue(Action.SMALL_ICON, SparkRes
					.getImageIcon(SparkRes.MODERATOR_IMAGE));
			if (admin && !userIsModerator) {
				moderatorAction.putValue(Action.NAME, Res
						.getString("menuitem.grant.moderator"));
				popup.add(moderatorAction);
			} else if (admin && userIsModerator && !isMe) {
				moderatorAction.putValue(Action.NAME, Res
						.getString("menuitem.revoke.moderator"));
				popup.add(moderatorAction);
			}
			
			
			if (admin) {
				JMenu unbanMenu = new JMenu(Res.getString("menuitem.unban"));
				Iterator bannedUsers = null;
				try {
					bannedUsers = chat.getOutcasts().iterator();
				} catch (XMPPException e) {
					Log.error("Error loading all banned users", e);
				}

				while (bannedUsers != null && bannedUsers.hasNext()) {
					Affiliate bannedUser = (Affiliate) bannedUsers.next();
					ImageIcon icon = SparkRes.getImageIcon(SparkRes.RED_BALL);
					JMenuItem bannedItem = new JMenuItem(bannedUser.getJid(),
							icon);
					unbanMenu.add(bannedItem);
					bannedItem.addActionListener(unbanAction);
				}

				if (unbanMenu.getMenuComponentCount() > 0) {
					popup.add(unbanMenu);
				}
			}
			}
			Action grantAdminAction = new AbstractAction() {
				public void actionPerformed(ActionEvent arg0) {
					try {
						if(selUserIsAdmin){
							chat.revokeAdmin(nickJIDMap.get(selectedUser));
						}else{
							chat.grantAdmin(nickJIDMap.get(selectedUser));
						}
					} catch (XMPPException e) {
						e.printStackTrace();
					}
				}
			};
			if(!selUserIsAdmin && !isMe){
				grantAdminAction.putValue(Action.NAME, "授予管理员");
			}else if(selUserIsAdmin && !isMe){
				grantAdminAction.putValue(Action.NAME, "取消管理员");
			}
			if(owner && !isMe){
				popup.add(grantAdminAction);
			}
		}

		Action inviteAction = new AbstractAction() {
			public void actionPerformed(ActionEvent actionEvent) {
				ConferenceUtils.inviteUsersToRoom(groupChatRoom
						.getConferenceService(), groupChatRoom.getRoomname(),
						null);
			}
		};

		inviteAction.putValue(Action.NAME, Res
				.getString("menuitem.invite.users"));
		inviteAction.putValue(Action.SMALL_ICON, SparkRes
				.getImageIcon(SparkRes.CONFERENCE_IMAGE_16x16));

		if (index != -1) {
			popup.addSeparator();
		}
		if(isAdminOrOwner){
			popup.add(inviteAction);
		}

		popup.show(participantsList, evt.getX(), evt.getY());
	}

	public void setNicknameChangeAllowed(boolean allowed) {
		allowNicknameChange = allowed;
	}

	public int getIndex(String name) {
		for (int i = 0; i < model.getSize(); i++) {
			JLabel label = (JLabel) model.getElementAt(i);
			if (label.getText().equals(name)) {
				return i;
			}
		}
		return -1;
	}
	/**
	 * 用户下线更改用户在线的图标为离线
	 * modified by sww
	 * @param displayName the users displayed name to remove.
	 */
	public synchronized void changeOnlineStatus(String displayName){
		try {
			for (int i = 0; i < users.size(); i++) {
				JLabel label = users.get(i);
				if (label.getText().equals(displayName)) {
					ImageIcon inviteIcon = getOfflineImageIcon(nickJIDMap.get(displayName));
					if(inviteIcon == null){
						SparkRes.getImageIcon(SparkRes.IM_MEMBER_UNAVAILABLE);
					}
					label.setIcon(inviteIcon);
					int currentOnlineIndex = statMap.size();
					if(i<currentOnlineIndex){
						JLabel lastOnlineuser = (JLabel)users.get(currentOnlineIndex);
						users.set(currentOnlineIndex,label);
						users.set(i,lastOnlineuser);
					}
				}
			}

			for (int i = 0; i < model.size(); i++) {
				JLabel label = (JLabel) model.getElementAt(i);
				if (label.getText().equals(displayName)) {
					ImageIcon inviteIcon = getOfflineImageIcon(nickJIDMap.get(displayName));
					if(inviteIcon == null){
						SparkRes.getImageIcon(SparkRes.IM_MEMBER_UNAVAILABLE);
					}
					label.setIcon(inviteIcon);
					//将离线用户和最后面的那个在线用户交换位置(如果离线的用户就是那个在线的用户则不用换)
					int currentOnlineIndex = statMap.size();
					if(i<currentOnlineIndex){
						JLabel lastOnlineuser = (JLabel)model.getElementAt(currentOnlineIndex);
						model.setElementAt(label, currentOnlineIndex);
						model.setElementAt(lastOnlineuser, i);
					}
				}
			}
		} catch (Exception e) {
			Log.error(e);
		}
	}

	/**
	 * Removes a user from the participant list based on their displayed name.
	 * 
	 * @param displayName
	 *            the users displayed name to remove.
	 */
	public synchronized void removeUser(String displayName) {
		try {
			for (int i = 0; i < users.size(); i++) {
				JLabel label = users.get(i);
				if (label.getText().equals(displayName)) {
					users.remove(label);
					model.removeElement(label);
				}
			}

			for (int i = 0; i < model.size(); i++) {
				JLabel label = (JLabel) model.getElementAt(i);
				if (label.getText().equals(displayName)) {
					users.remove(label);
					model.removeElement(label);
				}
			}
		} catch (Exception e) {
			Log.error(e);
		}
	}

	/**
	 * Adds a new user to the participant list.
	 * 
	 * @param userIcon
	 *            the icon to use initially.
	 * @param nickname
	 *            the users nickname.
	 */
	public synchronized void addUser(Icon userIcon, String nickname) {
		try {
			final JLabel user = new JLabel(nickname, userIcon,
					JLabel.HORIZONTAL);
			users.add(user);
			
			// Sort users alpha.
			Collections.sort(users, labelComp);
			
			// Add to the correct position in the model.
			final int index = users.indexOf(user);
			model.insertElementAt(user, index);
		} catch (Exception e) {
			Log.error(e);
		}
	}
	
	/**
	 * 添加成员
	 * modified by sidney
	 * @param userIcon
	 * @param nickname
	 */
	public void addMember(Affiliate aff){
		//首先根据jid获取数据库中ofmucmember标准对应的房间昵称,
		//如果数据库中的为空则取个人资料中的昵称，若个人资料中的昵称为空则取firstName
		//如果上面的信息都为空则取用户名
		//modified by sww
		String nick = "";
		nick = chat.getReservedNickname(aff.getJid());
		ImageIcon imageIcon = getOfflineImageIcon(aff.getJid());
//		Presence p = SparkManager.getConnection().getRoster().getPresence(aff.getJid());
//		if(p.getType()==Presence.Type.available){
//			imageIcon = SparkRes.getImageIcon(SparkRes.GREEN_BALL);
//		}
//		if(aff.getJid().equals(SparkManager.getSessionManager().getBareAddress())){
//			imageIcon = SparkRes.getImageIcon(SparkRes.GREEN_BALL);
//		}
		if(ModelUtil.hasLength(nick)){
			offlineMembers.add(new JLabel(nick,imageIcon, JLabel.HORIZONTAL));
			userMap.put(nick, aff.getJid());
			nickJIDMap.put(nick, aff.getJid());
			userNickMap.put(StringUtils.parseName(aff.getJid()), nick);
			return;
		}
		if(ModelUtil.hasLength(aff.getNick())){
			nick = aff.getNick();
		}else{
			VCard vcard = SparkManager.getVCardManager().getVCard(aff.getJid());
			String nickname = vcard.getNickName();
            if (ModelUtil.hasLength(nickname)) {
                nick = nickname;
            }else {
                String firstName = vcard.getFirstName();
                if (ModelUtil.hasLength(firstName)) {
                    nick = firstName;
                }else{
                	nick = StringUtils.parseName(aff.getJid());
                }
            }
		}
		offlineMembers.add(new JLabel(nick,imageIcon, JLabel.HORIZONTAL));
		userMap.put(nick, aff.getJid());
		nickJIDMap.put(nick, aff.getJid());
		userNickMap.put(StringUtils.parseName(aff.getJid()), nick);
	}
	
	/**
	 * 根据隶属关系获得用户上线对应的图标
	 * @param affiliate
	 * @return
	 */
	public ImageIcon getOnlineImageIcon(String jid){
		if(owners.contains(jid)){
			return SparkRes.getImageIcon(SparkRes.IM_CREATOR_AVAILABLE);
		}
		else if(admins.contains(jid)){
			return SparkRes.getImageIcon(SparkRes.IM_ADMINISTRATOR_AVAILABLE);
		}
		return null;
	}
	
	/**
	 * 根据隶属关系获得用户 下线对应的图标
	 * @param affiliate
	 * @return
	 */
	public ImageIcon getOfflineImageIcon(String jid){
		if(owners.contains(jid)){
			return SparkRes.getImageIcon(SparkRes.IM_CREATOR_UNAVAILABLE);
		}else if(admins.contains(jid)){
			return SparkRes.getImageIcon(SparkRes.IM_ADMINISTRATOR_UNAVAILABLE);
		}
		return SparkRes.getImageIcon(SparkRes.IM_MEMBER_UNAVAILABLE);
	}
	
	/**
	 * 根据昵称获取群成员
	 * modified by sidney
	 * @param nickName
	 * @return
	 */
	public JLabel getOfflineMember(String nickName){
		for (JLabel item: offlineMembers) {
			if(item.getName().equals(nickName))
				return item;
		}return null;
	}
	
	public JLabel getOnlineMember(String nickName){
		for (JLabel item: users) {
			if(item.getName().equals(nickName))
				return item;
		}return null;
	}
	
	/**
	 * 初始化成员信息，先将所有的成员包括(管理者、所有者、成员)都加入到membersMap中
	 * 在绘制界面方面，先将所以的人全都加入到不在线的members中，之后再监听presence的过程中对成员做处理
	 * modified by sidney
	 * 
	 */
	public synchronized void initMemebersInfo(){
		if(isInited) return ;
//		offlineMembers.clear();
//		model.clear();
//		users.clear();
		try {
    		for (Affiliate aff : chat.getOwners()) {
				membersMap.put(aff.getNick(),aff);
				owners.add(aff.getJid());
				addMember(aff);
				isInited = true;
			}
		} catch (XMPPException e) {
			e.printStackTrace();
		}
		try {
			for (Affiliate aff :chat.getAdmins()){
				membersMap.put(aff.getNick(),aff);
				admins.add(aff.getJid());
				addMember(aff);
				isInited = true;
			}
		} catch (XMPPException e) {
			e.printStackTrace();
		}
		try {
			for(Affiliate aff :chat.getMembers()){
				membersMap.put(aff.getNick(),aff);
				members.add(aff.getJid());
				addMember(aff);
				isInited = true;
			}
		} catch (XMPPException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		for (JLabel item: offlineMembers) {
			users.add(item);
			model.insertElementAt(item, offlineMembers.indexOf(item));
		}
	}
	
	public void addOfflineMember(){}
	
	public Set<String> getAdmins(){
		return admins;
	}
	
	public Set<String> getOwners(){
		return owners;
	}
	
	public Set<String> getMembers(){
		return members;
	}
	public boolean hasInRoom(String jid){
		if(members.contains(jid))return true;
		if(admins.contains(jid)) return true;
		if(owners.contains(jid)) return true;
		if(userMap.containsValue(jid)) return true;
		return false;
	}
	
	public boolean selectedUserIsAdmin(String jid){
		try {
			for (Affiliate aff :chat.getAdmins()){
				if(jid.equals(aff.getJid())){
					return true;
				}
			}
		} catch (XMPPException e) {
			e.printStackTrace();
		}
		return false;
	}
	
	public boolean userIsAdminOrOwner(String jid){
		try {
			for (Affiliate aff :chat.getAdmins()){
				if(jid.equals(aff.getJid())){
					return true;
				}
			}
		} catch (XMPPException e) {
			e.printStackTrace();
		}
		try {
			for (Affiliate aff :chat.getOwners()){
				if(jid.equals(aff.getJid())){
					return true;
				}
			}
		} catch (XMPPException e) {
			e.printStackTrace();
		}
		return false;
	}
	
	/**
	 * 根据用户的昵称设置管理员的图标,不过先要判断该用户是否在线
	 * @param nickname
	 */
	public void setAdminIcon(String nickname){
//		if(nickname == null){
//			nickname = userNickMap.get(StringUtils.parseName(SparkManager.getSessionManager().getJID()));
//		}
		Occupant occ= userManager.getOccupant(groupChatRoom, nickname);
		for (int i = 0; i < model.size(); i++) {
			JLabel label = (JLabel) model.getElementAt(i);
			if (label.getText().equals(nickname)) {
				if(occ == null){
					label.setIcon(SparkRes.getImageIcon(SparkRes.IM_ADMINISTRATOR_UNAVAILABLE));
				}else{
					label.setIcon(SparkRes.getImageIcon(SparkRes.IM_ADMINISTRATOR_AVAILABLE));
				}
			}
		}
	}
	
	public void cancelAdminIcon(String nickname){
//		if(nickname == null){
//			nickname = userNickMap.get(StringUtils.parseName(SparkManager.getSessionManager().getJID()));
//		}
		Occupant occ= userManager.getOccupant(groupChatRoom, nickname);
		for (int i = 0; i < model.size(); i++) {
			JLabel label = (JLabel) model.getElementAt(i);
			if (label.getText().equals(nickname)) {
				if(occ == null){
					label.setIcon(SparkRes.getImageIcon(SparkRes.IM_MEMBER_UNAVAILABLE));
				}else{
					label.setIcon(SparkRes.getImageIcon(SparkRes.IM_MEMBER_AVAILABLE));
				}
			}
		}
	}

	/**
	 * Sorts ContactItems.
	 */
	final Comparator<JLabel> labelComp = new Comparator<JLabel>() {
		public int compare(JLabel item1, JLabel item2) {
			return item1.getText().toLowerCase().compareTo(
					item2.getText().toLowerCase());
		}
	};

	/**
	 * The <code>JLabelIconRenderer</code> is the an implementation of
	 * ListCellRenderer to add icons w/ associated text in JComboBox and JList.
	 * 
	 * @author Derek DeMoro
	 */
	public class ParticipantRenderer extends JLabel implements ListCellRenderer {

		/**
		 * Construct Default JLabelIconRenderer.
		 */
		public ParticipantRenderer() {
			setOpaque(true);
		}

		public Component getListCellRendererComponent(JList list, Object value,
				int index, boolean isSelected, boolean cellHasFocus) {
			if (isSelected) {
				setBackground(list.getSelectionBackground());
				setForeground(list.getSelectionForeground());
			} else {
				setBackground(list.getBackground());
				setForeground(list.getForeground());
			}

			JLabel label = (JLabel) value;
			setText(label.getText());
			setIcon(label.getIcon());
			return this;
		}
	}
	
//	public void setIsInited(boolean b){
//		this.isInited = b;
//	}
}

